Analiza danych dotyczących baterii wykazała, że: - Najpowszechniej występują baterie litowo-jonowe. Posiadają one bardzo korzystny współczynnik gęstości energetycznej do ich masy, co może przekładać się na ich popularność, gdyż mogą być stosowane w lekkich urządzeniach mobilnych. - Atrybuty opisujące gęstość energii i pojemność względem masy i objęctości są silnie skorelowane. - Model liniowy nie daje satysfakcjonujących predykcji stabilności baterii.
library(dplyr)
library(ggcorrplot)
library(ggplot2)
library(ggthemes)
library(gridExtra)
library(kableExtra)
library(plotly)
library(caret)
Dane wczytane z pliku mp.batteries.csv.
df <- read.csv("mp_batteries.csv")
| Battery.ID | Battery.Formula | Working.Ion | Formula.Charge | Formula.Discharge | Max.Delta.Volume | Average.Voltage | Gravimetric.Capacity | Volumetric.Capacity | Gravimetric.Energy | Volumetric.Energy | Atomic.Fraction.Charge | Atomic.Fraction.Discharge | Stability.Charge | Stability.Discharge | Steps | Max.Voltage.Step |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| mp-30_Al | Al0-2Cu | Al | Cu | Al2Cu | 3.043399 | 0.0890331 | 1368.481 | 5562.790 | 121.84009 | 495.27253 | 0.0 | 0.6666667 | 0.0000000 | 0.0000000 | 1 | 0 |
| mp-1022721_Al | Al1-3Cu | Al | AlCu | Al3Cu | 1.243653 | -0.0215863 | 1112.937 | 4418.980 | -24.02423 | -95.38962 | 0.5 | 0.7500000 | 0.0740612 | 0.0962458 | 1 | 0 |
| mp-8637_Al | Al0-5Mo | Al | Mo | Al5Mo | 4.762574 | 0.1227568 | 1741.504 | 7175.702 | 213.78156 | 880.86651 | 0.0 | 0.8333333 | 0.4114601 | 0.0452120 | 1 | 0 |
| mp-129_Al | Al0-12Mo | Al | Mo | Al12Mo | 12.723893 | 0.0431214 | 2298.811 | 7346.232 | 99.12801 | 316.78006 | 0.0 | 0.9230769 | 0.0000000 | 0.0114456 | 1 | 0 |
| mp-91_Al | Al0-12W | Al | W | Al12W | 12.494598 | 0.0292342 | 1900.745 | 7332.719 | 55.56677 | 214.36621 | 0.0 | 0.9230769 | 0.0000000 | 0.0000000 | 1 | 0 |
| mp-1055908_Al | Al0-12Mn | Al | Mn | MnAl12 | 18.236156 | 0.0397314 | 2547.693 | 7592.916 | 101.22330 | 301.67688 | 0.0 | 0.9230769 | 0.1454643 | 0.0000000 | 1 | 0 |
Zbiór zawiera dane o materiałach wykorzystywanych w bateriach. Uwzględnia ich skład chemiczny i parametry wydajnościowe.
Zbiór danych posiada:
Źródło: “Programowanie w R: Projekt - Wymagania”
Podstawowe statystyki
| Battery.ID | Battery.Formula | Working.Ion | Formula.Charge | Formula.Discharge | Max.Delta.Volume | Average.Voltage | Gravimetric.Capacity | Volumetric.Capacity | Gravimetric.Energy | Volumetric.Energy | Atomic.Fraction.Charge | Atomic.Fraction.Discharge | Stability.Charge | Stability.Discharge | Steps | Max.Voltage.Step | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Length:4351 | Length:4351 | Length:4351 | Length:4351 | Length:4351 | Min. : 0.00002 | Min. :-7.755 | Min. : 5.176 | Min. : 24.08 | Min. :-583.5 | Min. :-2208.1 | Min. :0.00000 | Min. :0.007407 | Min. :0.00000 | Min. :0.00000 | Min. :1.000 | Min. : 0.0000 | |
| Class :character | Class :character | Class :character | Class :character | Class :character | 1st Qu.: 0.01747 | 1st Qu.: 2.226 | 1st Qu.: 88.108 | 1st Qu.: 311.62 | 1st Qu.: 211.7 | 1st Qu.: 821.6 | 1st Qu.:0.00000 | 1st Qu.:0.086957 | 1st Qu.:0.03301 | 1st Qu.:0.01952 | 1st Qu.:1.000 | 1st Qu.: 0.0000 | |
| Mode :character | Mode :character | Mode :character | Mode :character | Mode :character | Median : 0.04203 | Median : 3.301 | Median : 130.691 | Median : 507.03 | Median : 401.8 | Median : 1463.8 | Median :0.00000 | Median :0.142857 | Median :0.07319 | Median :0.04878 | Median :1.000 | Median : 0.0000 | |
| NA | NA | NA | NA | NA | Mean : 0.37531 | Mean : 3.083 | Mean : 158.291 | Mean : 610.62 | Mean : 444.1 | Mean : 1664.0 | Mean :0.03986 | Mean :0.159077 | Mean :0.14257 | Mean :0.12207 | Mean :1.167 | Mean : 0.1503 | |
| NA | NA | NA | NA | NA | 3rd Qu.: 0.08595 | 3rd Qu.: 4.019 | 3rd Qu.: 187.600 | 3rd Qu.: 722.75 | 3rd Qu.: 614.4 | 3rd Qu.: 2252.3 | 3rd Qu.:0.04762 | 3rd Qu.:0.200000 | 3rd Qu.:0.13160 | 3rd Qu.:0.09299 | 3rd Qu.:1.000 | 3rd Qu.: 0.0000 | |
| NA | NA | NA | NA | NA | Max. :293.19322 | Max. :54.569 | Max. :2557.627 | Max. :7619.19 | Max. :5926.9 | Max. :18305.9 | Max. :0.90909 | Max. :0.993333 | Max. :6.48710 | Max. :6.27781 | Max. :6.000 | Max. :26.9607 | |
| Unique: 4351 | Unique: 3301 | Unique: 10 | Unique: 2096 | Unique: 3173 | Unique: 4342 | Unique: 4351 | Unique: 3330 | Unique: 4342 | Unique: 4351 | Unique: 4351 | Unique: 126 | Unique: 192 | Unique: 3050 | Unique: 3933 | Unique: 6 | Unique: 600 |
W zbiorze występują następujące atrybuty numeryczne:
Jak widać dystrybucja atrybutów zawiera wiele outlierów ponad trzecim kwartylem. Można je usunąć. Wyjątkiem będzie kolumna Steps, ponieważ zawiera dyskretne wartości, których niektóre wartości występują zacząco rzadziej. Usunięcie outlierów na podstawie tego atrybutu może doprowadzić do utraty istotnych danych. Podobnie usuwnie
outlier_detection_param = 3.2
remove_outliers <- function(df, columns) {
for (col in columns) {
Q3 <- quantile(df[[col]], 0.75)
IQR <- IQR(df[[col]])
threshold <- Q3 + outlier_detection_param * IQR
ret_df <- df[df[[col]] <= threshold, ]
}
return(ret_df)
}
columns_to_clean <- setdiff(numeric_columns_names, c("Steps", "Max.Voltage.Step"))
df_clean <-
remove_outliers(df, columns_to_clean) %>%
filter(
Max.Delta.Volume < 0.5,
Average.Voltage > -2, Average.Voltage < 9,
Gravimetric.Energy < 2000,
Volumetric.Energy < 6500,
Volumetric.Capacity < 2000,
Atomic.Fraction.Charge < 0.4,
Stability.Charge < 0.6,
Max.Voltage.Step < 2
)
Wybór outlierów do usunięcia polega na standardowej metodzie wykorzystującej trzeci kwartyl i rozstęp międzykwartylowy i usunięcia wierszy w których te outliery się znajdują. Analiza wykresów pudełkowych wskazuje, że outliery występują niemal wyłącznie w górnym przedziale wartośści atrybutów. Dlatego też do wykrywania outlierów wykorzystano następujący wzór:
\[ O = \{x: \exists_{a \text{ jest atrybutem } x} a > Q3 + 3.2 * IQR \} \]
Parametr 3.2 został dobrany tak, aby w zbiorze pozostało około 90% wierszy.
Ponadto, dodatkowe pojedyncze outliery zostały usunięte poprzez ręczną analizę wykresów pudełkowych.
Po usunięciu outlierów zbiór posiada 3896 wierszy, co stanowi 90% oryginalnego zbioru.
Atrybuty nominalne:
Tylko kolumna Working.Ion posiada liczbę unikalnych wartości która nadaje się do wizualizacji.
Zdecydowaną większość baterii w zbiorze stanowią baterie litowo-jonowe.
Można zauważyć, że ogniwa litowo-jonowe charakteryzują się średnio większą pojemnością na jednostkę masy (są lekkie), a cynkowe i itrowe mają korzystniejszy stosunek objętości do pojemności (są mniejsze).
Bardzo podobną zależność można zauważyć jeśli chodzi o energię baterii. Litowe posiadają więcej energii wziędem jednostki masy, a cynkowe i itrowe względem objętości.
Można rówież zauważyć, że wszystkie cztery atrybuty posiadają silną korelację ze sobą.
Analiza wykresu nie pozwala stwierdzić zależności między stabilnością a użytym jonem.
Współczynnik korelacji zwykle uznaje się za wysoki gdy jego wartość bezwzględna przekracza 0.7.
Biorąc pod uwagę opisy atrybutów, można spodziewać się silnej korelacji między parami: Gravimetric/Volumetric Capacity i Energy. Odnoszą się do podobnego pojęcia dotyczącego pojemności i gęstości energii w baterii wyrażonych względem różnych jednostek. Można również spodziewać się korelacji między gęstością i pojemnością baterii - im większa gęstość, tym większa pojemność na jednostkę masy.
| Atrybut 1 | Atrybut 2 | Współczynnik korelacji |
|---|---|---|
| Gravimetric.Energy | Volumetric.Energy | 0.912 |
| Gravimetric.Capacity | Volumetric.Capacity | 0.873 |
| Gravimetric.Capacity | Gravimetric.Energy | 0.771 |
| Gravimetric.Capacity | Volumetric.Energy | 0.762 |
| Steps | Max.Voltage.Step | 0.756 |
| Volumetric.Capacity | Volumetric.Energy | 0.737 |
| Atomic.Fraction.Charge | Atomic.Fraction.Discharge | 0.703 |
Oczekiwane korelacje wystąpiły z najwyższymi wartościami współczynnika.
Wysoką korelację wykazały atrybuty Steps i Max Voltage Step. Możliwe że jest to spowodowane rozkładem wartości skoncentrowanym w znacznym stopniu na podobnych wartościach.
ggplotly(
ggplot(df_clean, aes(Steps,Max.Voltage.Step)) +
geom_point(position = position_jitter(0.2, 0.17)) +
geom_smooth(method="lm") +
theme_minimal()
)
Na wykresie można zauważyć że wysoka korelacja jest wynikiem bardzo dużej liczby instancji z parami wartości Steps = 1 i Max Voltage Step = 0, które dominują w zbiorze. Nie uznawałbym tego wyniku za znaczący.
Wysoką korelację wykazały również atrybuty Atomic Fraction Charge i Atomic Fraction Discharge.
ggplotly(
ggplot(df_clean, aes(Atomic.Fraction.Charge, Atomic.Fraction.Discharge)) +
geom_point(position = position_jitter()) +
geom_smooth(method="lm") +
theme_minimal()
)
W zbiorze występuje znacząca liczba instancji z Atomic Fraction Charge = 0. Ten wynik można interpretować jako brak udzału atomowego składników w stanie naładowania.
df_positive_afc <- df_clean %>%
filter(Atomic.Fraction.Charge > 0) %>%
select(Atomic.Fraction.Charge, Atomic.Fraction.Discharge)
cor_chrg_dschrg <- cor_matrix["Atomic.Fraction.Charge", "Atomic.Fraction.Discharge"]
cor_chrg_dschrg_pos <- cor(df_positive_afc)["Atomic.Fraction.Charge", "Atomic.Fraction.Discharge"]
Pozostałe wartości wykazują jednak silną korelację, tj. o wartości 0.836, w porównaniu do ogólnej wartości korelacji tych kolumn, któa wyniosła 0.703. Można więc przyjąć, że dla Atomic Fraction Charge > 0, istnieje korelacja z Atomic Fraction Discharge.
Do dokonania predykcji stabilności materiału, wykorzystane zostaną następujące atrybuty: - Working Ion - Max Delta Volume - Average Voltage - Gravimetric Energy - Atomic Fraction Charge
Zostały wybrane tak, aby nie brać pod uwagę kilku atrybutów o silnej korelacji. Wykorzystany zostanie model liniowy.
df_x_data <- df_clean %>%
select(
Working.Ion,
Max.Delta.Volume,
Average.Voltage,
Gravimetric.Energy,
Atomic.Fraction.Charge
)
df_y_result_charge <- df_clean$Stability.Charge
df_y_result_discharge <- df_clean$Stability.Discharge
train_model <- function(x_set, y_set) {
set.seed(42)
data_index <- createDataPartition(y_set, p = 0.8, list = FALSE)
x_train <- x_set[data_index,]
x_test <- x_set[-data_index,]
y_train <- y_set[data_index]
y_test <- y_set[-data_index]
model <- lm(y_train ~ ., data = as.data.frame(x_train))
list(model = model, x_train = x_train, x_test = x_test, y_train = y_train, y_test = y_test)
}
get_prediction_results <- function(model_list){
y_pred <- predict(model_list$model, newdata = as.data.frame(model_list$x_test))
df_results <- data.frame(y_pred, y_test = model_list$y_test)
# Calculate Mean Squared Error (MSE)
mse <- mean((model_list$y_test - y_pred)^2)
prediction_volum <- ggplot(df_results, aes(x = y_test, y = y_pred,
text = paste("Actual:", round(y_test, 2), "Predicted:", round(y_pred, 2)))) +
geom_point() +
geom_abline(slope = 1, intercept = 0, color = "red") +
labs(
x = "Actual",
y = "Predicted"
) +
theme_minimal()
list(plot = ggplotly(prediction_volum, tooltip = "text"), mse = mse)
}
model_charge_data <- train_model(df_x_data, df_y_result_charge)
model_discharge_data <- train_model(df_x_data, df_y_result_discharge)
list_charge <- get_prediction_results(model_charge_data)
list_discharge <- get_prediction_results(model_discharge_data)
MSE: 0.005241
MSE: 0.0024106
Model liniowy nie najlepiej nadaje się do predykcji wzkaźnika stabilności materiału ze względu na stosunkowo wysoki współczynnik MSE.
Można ulepszyć model dokonując normalizacji danych, dokonania bardziej restrykcyjnego usunięcia outlierów, wybór innego modelu lub innych atrybutów.